<template>
  <div class="form-single-fragment third-party-dlg" style="position: relative">
    <el-form
      ref="form"
      :model="formData"
      class="full-width-input"
      :rules="rules"
      style="width: 100%"
      label-width="100px"
      :size="formItemSize"
      label-position="right"
      @submit.prevent
    >
      <el-row :gutter="20">
        <el-col :span="24">
          <el-form-item label="脚本名称" prop="OnlineApi.apiName">
            <el-input
              class="input-item"
              v-model="formData.OnlineApi.apiName"
              :clearable="true"
              placeholder="请输入脚本名称"
            />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="脚本编码" prop="OnlineApi.apiCode">
            <el-input
              class="input-item"
              v-model="formData.OnlineApi.apiCode"
              :clearable="true"
              placeholder="请输入英文字符，并保证系统内唯一"
            />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="脚本分组" prop="OnlineApi.groupId">
            <el-select
              class="input-item"
              v-model="formData.OnlineApi.groupId"
              placeholder="请选择脚本分组"
              disabled
            >
              <el-option
                v-for="item in groupList"
                :key="item.groupId"
                :label="item.groupName"
                :value="item.groupId"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="脚本描述" prop="OnlineApi.apiDesc">
            <el-input
              class="input-item"
              v-model="formData.OnlineApi.apiDesc"
              type="textarea"
              :rows="3"
              placeholder="请输入脚本描述"
            />
          </el-form-item>
        </el-col>
      </el-row>

      <!-- API参数配置 -->
      <el-row style="margin-top: 20px">
        <el-col :span="24">
          <div class="param-header">
            <span class="param-title">参数配置</span>
            <el-button type="primary" link @click="onAddParam"> 添加参数 </el-button>
          </div>
          <vxe-table
            :data="formData.OnlineApi.paramList"
            border
            show-overflow="title"
            show-header-overflow="title"
            :row-config="{ height: 35, isHover: true }"
            height="300px"
          >
            <vxe-column type="seq" title="序号" width="60" />
            <vxe-column title="参数名称" field="paramName">
              <template #default="{ row }">
                <el-input v-model="row.paramName" placeholder="参数名称" />
              </template>
            </vxe-column>
            <vxe-column title="参数描述" field="paramDesc">
              <template #default="{ row }">
                <el-input v-model="row.paramDesc" placeholder="参数描述" />
              </template>
            </vxe-column>
            <vxe-column title="参数类型" field="paramType" width="150">
              <template #default="{ row }">
                <el-select v-model="row.paramType" placeholder="参数类型" style="width: 100%">
                  <el-option label="字符串" value="String" />
                  <el-option label="数值型" value="Number" />
                  <el-option label="日期类型" value="Date" />
                  <el-option label="布尔类型" value="Boolean" />
                  <el-option label="JSON对象" value="Object" />
                  <el-option label="JSON数组" value="Array" />
                </el-select>
              </template>
            </vxe-column>
            <vxe-column title="是否必填" field="required" width="100">
              <template #default="{ row }">
                <el-switch v-model="row.required" />
              </template>
            </vxe-column>
            <vxe-column title="操作" width="100" fixed="right">
              <template #default="{ row }">
                <el-button link type="danger" @click="onDeleteParam(row)"> 删除 </el-button>
              </template>
            </vxe-column>
            <template #empty>
              <div class="table-empty unified-font">
                <img src="@/assets/img/empty.png" />
                <span>暂无数据</span>
              </div>
            </template>
          </vxe-table>
        </el-col>
      </el-row>
    </el-form>
    <el-row class="no-scroll flex-box menu-box" type="flex" justify="end" style="margin-top: 20px">
      <el-button :size="formItemSize" :plain="true" @click="onCancel"> 取消 </el-button>
      <el-button type="primary" :size="formItemSize" @click="onSubmit()"> 保存 </el-button>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { FormItemRule, ElMessage } from 'element-plus';
import { Arrayable } from 'element-plus/es/utils/typescript';
import { Plus, EditPen } from '@element-plus/icons-vue';
import { VxeTable, VxeColumn } from 'vxe-table';
import OnlineApiController from '@/api/online/OnlineApiController';
import { DialogProp } from '@/components/Dialog/types';
import { ANY_OBJECT } from '@/types/generic';
import { useThirdParty } from '@/components/thirdParty/hooks';
import { ThirdProps } from '@/components/thirdParty/types';
import { useLayoutStore } from '@/store';
import { OnlineApi, OnlineApiGroup } from '@/types/online/script';
import { Dialog } from '@/components/Dialog';

const layoutStore = useLayoutStore();

interface IProps extends ThirdProps {
  id?: number;
  rowData?: OnlineApi;
  groupId?: number;
  groupList?: OnlineApiGroup[];
  // 当使用Dialog.show弹出组件时，须定义该prop属性，以便对dialog进行回调
  dialog?: DialogProp<ANY_OBJECT>;
}

const props = defineProps<IProps>();
const { thirdParams, onCloseThirdDialog } = useThirdParty(props);
const formItemSize = computed(() => {
  return layoutStore.defaultFormItemSize || thirdParams.value.defaultFormItemSize?.value;
});

const form = ref();

const formData = reactive<ANY_OBJECT>({
  OnlineApi: {
    id: undefined,
    apiName: undefined,
    apiCode: undefined,
    groupId: undefined,
    apiDesc: undefined,
    apiScript: undefined,
    extraData: undefined,
  },
});

const groupList = computed(() => {
  return props.groupList || thirdParams.value.groupList || [];
});

const rules: Partial<Record<string, Arrayable<FormItemRule>>> = {
  'OnlineApi.apiName': [
    {
      required: true,
      message: '请输入脚本名称',
      trigger: 'blur',
    },
  ],
  'OnlineApi.apiCode': [
    {
      required: true,
      message: '请输入脚本编码',
      trigger: 'blur',
    },
    {
      type: 'string',
      pattern: /^[A-Za-z0-9_]+$/,
      message: '请输入英文字符，并保证系统内唯一',
      trigger: 'blur',
    },
  ],
  'OnlineApi.groupId': [
    {
      required: true,
      message: '请选择脚本分组',
      trigger: 'change',
    },
  ],
};

const dialogParams = computed(() => {
  return {
    id: props.id || thirdParams.value.id,
    rowData: props.rowData || thirdParams.value.rowData,
    groupId: props.groupId || thirdParams.value.groupId,
  };
});

const isEdit = computed(() => {
  return dialogParams.value.id != null && dialogParams.value.id !== '';
});

const onCancel = () => {
  if (props.dialog) {
    props.dialog.cancel();
  } else {
    onCloseThirdDialog(false);
  }
};

/**
 * 保存
 */
const onSubmit = () => {
  form.value.validate((valid: boolean) => {
    if (!valid) return;
    if (formData.OnlineApi.apiName == null || formData.OnlineApi.apiCode == null) {
      ElMessage.error('请求失败，发现必填参数为空！');
      return;
    }

    let params = {
      onlineApiDto: {
        id: isEdit.value ? dialogParams.value.id : undefined,
        apiName: formData.OnlineApi.apiName,
        apiCode: formData.OnlineApi.apiCode,
        groupId: formData.OnlineApi.groupId,
        apiDesc: formData.OnlineApi.apiDesc,
        apiScript: formData.OnlineApi.apiScript,
        extraData: JSON.stringify(formData.OnlineApi.paramList || []),
      },
    };

    let httpCall = isEdit.value
      ? OnlineApiController.update(params)
      : OnlineApiController.add(params);
    httpCall
      .then(res => {
        ElMessage.success('保存成功');
        if (props.dialog) {
          props.dialog.submit(res);
        } else {
          onCloseThirdDialog(true);
        }
      })
      .catch(e => {
        console.warn(e);
      });
  });
};

/**
 * 重置表单数据
 */
const resetFormData = () => {
  form.value.resetFields();
};

/**
 * 获取脚本详细信息
 */
const loadApiData = () => {
  return new Promise((resolve, reject) => {
    if (isEdit.value) {
      if (dialogParams.value.id == null) {
        resetFormData();
        reject();
        return;
      }
      let params = { id: dialogParams.value.id };
      OnlineApiController.view(params)
        .then(res => {
          formData.OnlineApi = {
            ...res.data,
            paramList: res.data.extraData ? JSON.parse(res.data.extraData) : [],
          };
          resolve(res);
        })
        .catch(e => {
          reject(e);
        });
    } else {
      // 新建时设置默认分组
      if (dialogParams.value.groupId) {
        formData.OnlineApi.groupId = dialogParams.value.groupId;
      }
      formData.OnlineApi.paramList = [];
      resolve(null);
    }
  });
};

/**
 * 添加参数
 */
const onAddParam = () => {
  formData.OnlineApi.paramList.push({
    paramName: '',
    paramType: 'String',
    required: false,
    paramDesc: '',
  });
};

/**
 * 删除参数
 */
const onDeleteParam = (row: ANY_OBJECT) => {
  const index = formData.OnlineApi.paramList.indexOf(row);
  if (index > -1) {
    formData.OnlineApi.paramList.splice(index, 1);
  }
};

const formInit = () => {
  loadApiData().catch(e => {
    console.warn(e);
  });
};

onMounted(() => {
  // 初始化页面数据
  formInit();
});
</script>

<style scoped>
.form-script-manage {
  height: 100%;
}
.param-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}
.param-title {
  font-size: 16px;
  font-weight: bold;
}
.table-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px 0;
}
.table-empty img {
  width: 100px;
  height: 100px;
  margin-bottom: 8px;
}
</style>
